package com.oldking.utils;

import com.baidu.aip.speech.AipSpeech;
import com.baidu.aip.speech.TtsResponse;
import com.baidu.aip.util.Util;
import javazoom.jl.player.Player;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
//import sun.misc.BASE64Decoder;

/**
 * 将文本上传至百度服务器，返回语音文件，如output.mp3，并播放MP3文件
 * SDK下载地址：https://ai.baidu.com/file/EDF42F3DB3B4489FA1A88FD1E2BC5D74
 */
public class VoiceComposeUtil {
    // 设置APPID/AK/SK
    // 百度AI开发平台的控制台中创建一个语音应用即可获得
    private static final String APP_ID = "";
    // 百度
    private static final String API_KEY = "";
    // 百度
    private static final String SECRET_KEY = "";
    // 百度
    private static final AipSpeech aipSpeech = getAipSpeech();

    private static Player player;
    // 华为云语音合成
//    private static final int DEFAULT_PITCH = 0;
//    private static final int DEFAULT_SPEED = 0;
//    private static final int DEFAULT_VOLUME = 50;
//    // 华为云语音合成
//    private static String ak = "";
//    private static String sk = "";
//    private static String region = "cn-east-3";    // 区域，如cn-north-1、cn-north-4
//    private static String projectId = ""; // 项目id。登录管理控制台，鼠标移动到右上角的用户名上，在下拉列表中选择我的凭证，在项目列表中查看项目id。多项目时，展开“所属区域”，从“项目ID”列获取子项目ID。
    // 华为云语音合成// 待合成的文本
         // 设置本地音频保存路径.可选择不保存到本地。需具体到文件，如D:/test.wav


    public static void main(String[] args) {
        // 华为云语音合成   // 设置property，特征字符串，{language}_{speaker}_{domain}
       // ttsCustom(0, 0, 50,"这时一个，喜出望外的日子。老王赶忙掏出了个价值不菲的子给她" ,"chinese_xiaoyu_common","F:/555555.mp3");
// 百度云语音合成
        String filename = "F:\\work\\test\\output2.mp3";
        String text = "在一个风雪交加的白天。老王一听这消息，喜出望外赶忙掏出了个价值不菲的子给她！";
        if(!VoiceComposeUtil.getMP3ByText(filename, text, "5", "8", "5", "1")){
            System.out.println("转换失败");
        }else{
            VoiceComposeUtil.playMP3(filename);
        }
    }


    /**
     * 用于语音合成参数设置，例如发声人、音高、语速、音量、采样率、连接超时。所有参数均可以不设置，采用默认。
     *
     * @param request 语音合成请求
     */
//    private static void setParameter(TtsCustomRequest request, int pitch, int speed, int vol, String property, String targetPath) {
//
//        // 设置语音格式，可选MP3，pcm等，默认wav
//        request.setAudioFormat("mp3");
//        // 音高，[-500, 500], 默认0
//        request.setPitch(pitch);
//        // 语速，[-500, 500]，默认0
//        request.setSpeed(speed);
//        // 音量，[0, 100]，默认50
//        request.setVolume(vol);
//        // 当前支持8000和16000，默认8000
//        request.setSampleRate("8000");
//        // 设置property，特征字符串，{language}_{speaker}_{domain}
//        request.setProperty(property);
//
//        // 设置返回数据是否保存，默认不保存。若保存，则需要设置一下保存路径，如D:/1.wav
//        request.setSaved(true);
//        request.setSavePath(targetPath);
//    }

    /**
     * 定义config，所有参数可选，设置超时时间等。
     *
     * @return SisConfig
     */
//    private static SisConfig getConfig() {
//        SisConfig config = new SisConfig();
//        // 设置连接超时，默认10000ms
//        config.setConnectionTimeout(SisConstant.DEFAULT_CONNECTION_TIMEOUT);
//        // 设置读取超时，默认10000ms
//        config.setReadTimeout(SisConstant.DEFAULT_READ_TIMEOUT);
//        // 设置代理, 一定要确保代理可用才启动此设置。 代理初始化也可用不加密的代理，new ProxyHostInfo(host, port);
////         ProxyHostInfo proxy = new ProxyHostInfo("proxy.huawei.com", 8080, "wwx964397", "QQ.4806221");
////         config.setProxy(proxy);
//        return config;
//    }

    /**
     * 根据文本和api，获取生成的音频数据
     */
//    public static void ttsCustom(int pitch, int speed, int vol, String text,String property, String targetPath) {
//        try {
//            // 1. 初始化TtsCustomizationClient
//            // 定义authInfo，根据ak，sk，region, projectId.
//            AuthInfo authInfo = new AuthInfo(ak, sk, region, projectId);
//            // 定义config，所有参数可选，设置超时时间。
//            SisConfig config = getConfig();
//            // 根据authInfo和config，构造TtsCustomizationClient
//            TtsCustomizationClient tts = new TtsCustomizationClient(authInfo, config);
//
//            // 2. 配置请求
//            TtsCustomRequest request = new TtsCustomRequest(text);
//            // 设置参数，所有参数均可选，如果要保存合成音频文件，需要在request设置
//            setParameter(request, pitch, speed, vol, property, targetPath);
//
//            // 3. 发送请求，获取响应。具体结果可通过response.getXX获取。
//            TtsCustomResponse response = tts.getTtsResponse(request);
////            System.out.println(JsonUtils.obj2Str(response, true));
//            decoderBase64File(response.getResult().getData(),targetPath);
//        } catch (SisException e) {
//            e.printStackTrace();
//        }
//
//    }
//    private static void decoderBase64File(String base64Code, String targetPath){
//        try{
//            byte[] buffer = new BASE64Decoder().decodeBuffer(base64Code);
//            FileOutputStream out = new FileOutputStream(targetPath);
//            out.write(buffer);
//            out.close();
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//    }

    public static AipSpeech getAipSpeech() {
        // 初始化一个AipSpeech
        AipSpeech aipSpeech = new AipSpeech(APP_ID, API_KEY, SECRET_KEY);

        // 可选：设置网络连接参数
        aipSpeech.setConnectionTimeoutInMillis(2000);
        aipSpeech.setSocketTimeoutInMillis(60000);

        // 可选：设置代理服务器地址, http和socket二选一，或者均不设置
        //aipSpeech.setHttpProxy("proxy_host", proxy_port);  // 设置http代理
        //aipSpeech.setSocketProxy("proxy_host", proxy_port);  // 设置socket代理

        // 可选：设置log4j日志输出格式，若不设置，则使用默认配置
        // 也可以直接通过jvm启动参数设置此环境变量
        // System.setProperty("aip.log4j.conf", "path/to/your/log4j.properties");

        return aipSpeech;
    }

//  百度生成mp3
    /**
     * 将文字转为MP3文件，需联网，依靠百度语音合成
     * @param text
     * @return 是否成功
     */
    public static boolean getMP3ByText(String filename, String text, String spd, String pit, String vol, String per){
        player = null;

        // 设置可选参数
        HashMap<String, Object> options = new HashMap<>();
        // 语速，取值0-9，默认为5中语速
        options.put("spd", spd);
        // 音调，取值0-9，默认为5中语调
        options.put("pit", pit);
        // 音量，取值0-15，默认为5中音量
        options.put("vol", vol);
        // 发音人选择, 0为女声，1为男声，3为情感合成-度逍遥，4为情感合成-度丫丫，默认为普通女
        options.put("per", per);

        // 调用接口
        // text 合成的文本，使用UTF-8编码。小于2048个中文字或者英文数字。（文本在百度服务器内转换为GBK后，长度必须小于4096字节）
        // lang 固定值zh。语言选择,目前只有中英文混合模式，填写固定值zh
        // ctp 客户端类型选择，web端填写固定值1
        TtsResponse res = aipSpeech.synthesis(text, "zh", 1, options);
        // 如果合成成功,下行数据为二进制语音文件，包含在data中。 如果合成出现错误，则会填充返回值到result中。
        // 若请求错误，服务器将返回的JSON文本包含以下参数：
        // error_code：错误码。
        // error_msg：错误描述信息，帮助理解和解决发生的错误。
        byte[] data = res.getData();
        JSONObject json = res.getResult();
        if (data != null) {
            try {
                Util.writeBytesToFileSystem(data, filename);
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }

        if (json != null) {
            System.out.println(json.toString(2));
        }

        return true;
    }

    /**
     * 将文字转为MP3文件，需联网，依靠百度语音合成
     *
     * @param
     * @return 是否成功
     */
//    public static boolean getMP3ByText(String filename, String text, String spd, String pit, String vol, String per) {
//        player = null;
//
//        // 设置可选参数
//        HashMap<String, Object> options = new HashMap<>();
//        // 语速，取值0-9，默认为5中语速
//        options.put("spd", spd);
//        // 音调，取值0-9，默认为5中语调
//        options.put("pit", pit);
//        // 音量，取值0-15，默认为5中音量
//        options.put("vol", vol);
//        // 发音人选择, 0为女声，1为男声，3为情感合成-度逍遥，4为情感合成-度丫丫，默认为普通女
//        options.put("per", per);
//
//        // 调用接口
//        // text 合成的文本，使用UTF-8编码。小于2048个中文字或者英文数字。（文本在百度服务器内转换为GBK后，长度必须小于4096字节）
//        // lang 固定值zh。语言选择,目前只有中英文混合模式，填写固定值zh
//        // ctp 客户端类型选择，web端填写固定值1
//        TtsResponse res = aipSpeech.synthesis(text, "zh", 1, options);
//        // 如果合成成功,下行数据为二进制语音文件，包含在data中。 如果合成出现错误，则会填充返回值到result中。
//        // 若请求错误，服务器将返回的JSON文本包含以下参数：
//        // error_code：错误码。
//        // error_msg：错误描述信息，帮助理解和解决发生的错误。
//        byte[] data = res.getData();
//        JSONObject json = res.getResult();
//        if (data != null) {
//            try {
//                Util.writeBytesToFileSystem(data, filename);
//            } catch (IOException e) {
//                e.printStackTrace();
//                return false;
//            }
//        }
//
//        if (json != null) {
//            System.out.println(json.toString(2));
//        }
//
//        return true;
//    }

    public static void playMP3(String name) {
        try {
            BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(name));
            // 需导入javazoom.jl.player.Player，下载地址http://www.javazoom.net/javalayer/sources/jlayer1.0.1.zip
            player = new Player(buffer);
            player.play();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public static String playerStatus() {
        if (player == null) {
            return "null";
        } else if (player.isComplete()) {
            return "played";
        } else {
            return "playing";
        }
    }
}